import sys
import asyncio
from PyQt5.QtCore import QThread, pyqtSignal
from MyTT import EMA
import numpy as np
import pandas as pd
from tqsdk import TqApi
from db_manager import connect_db, get_monitored_products
import time 
class AsyncOpenCloseStrategy(QThread):
    def __init__(self, api, symbols, lots):
        # 调用父类的初始化方法
        super().__init__()
        self.api = api
        self.symbols = symbols
        self.lots = lots
        self.running = False
        self.main_task = None
        self.active_symbols = set()  # 新增运行状态跟踪
        self.loop = asyncio.new_event_loop()

    #线程启动时执行，线程启动后会启动调用run方法，在这里重写run方法
    def run(self):
        print("************************已启动策略************************")
        self.running = True
        if self.main_task:
            self.main_task.cancel()

        asyncio.set_event_loop(self.loop)        
        try:
            # 使用loop.create_task
            #tasks = [self.loop.create_task(self._process_product(symbol)) for symbol in self.symbols]
            self.loop.run_until_complete(self._run_all_symbols())
        except Exception as e:
            #print(f"错误: {str(e)}")
            pass
        finally:
            self.loop.close()

        return self.main_task

    # async   def start(self):
    #     """启动策略（协程版本）"""
    #     print("************************已启动策略************************")
    #     self.running = True
    #     if self.main_task:
    #         self.main_task.cancel()

    #     await self._run_all_symbols()
    #     return self.main_task

    async def _run_all_symbols(self):
        """并行处理所有品种"""
        print(f"开始处理品种列表: {self.symbols}")
        # 使用当前循环创建任务
        tasks = [asyncio.create_task(self._process_product(symbol)) for symbol in self.symbols]
        await asyncio.gather(*tasks)

    async def _process_product(self, symbol):
        """单个品种处理协程"""
        self.active_symbols.add(symbol)
        print(f"开始处理品种: {symbol}")
        try:
            klines = self.api.get_kline_serial(symbol, 5*60, 500)
            while self.running:
                print(f"{time.time('%X')} {symbol} 正在运行...")  # 添加flush确保及时输出
                #deadline = time.time() + 0.5
                #await self.api.wait_update(deadline=deadline)  # 等待0.5秒  
                await asyncio.sleep(1)  # 指定循环
                # async with self.api.register_update_notify() as update_chan:
                #     async for _ in update_chan:
                #         if self.api.is_changing(klines.iloc[-1], "datetime"):
                if not klines.close.iloc[-1]:
                    print("K线已变化")
                    q = (3*klines.close + klines.low + klines.open + klines.high) / 6
                    ma_values = self._calculate_ma(q)
                    short_ma = ma_values['ma']
                    ema_7 = ma_values['ema']
                    
                    position = self.api.get_position(symbol)
                    
                    # 平空仓逻辑
                    if short_ma[-2] > ema_7[-2]:  
                        if position.pos_short > 0:
                            self.api.insert_order(symbol, direction="BUY", offset="CLOSE", 
                                            volume=position.pos_short)
                    # 开多仓逻辑
                    if position.pos_long == 0 and position.pos_short == 0 and short_ma[-3] < ema_7[-3] and short_ma[-2] > ema_7[-2]:
                        self.api.insert_order(symbol, direction="BUY", offset="OPEN", 
                                        volume=self.lots)
                        
                    # 平多仓逻辑
                    if short_ma[-2] < ema_7[-2]:  
                        if position.pos_long > 0:
                            self.api.insert_order(symbol, direction="SELL", offset="CLOSE", 
                                            volume=position.pos_long)
                    # 开空仓逻辑
                    if position.pos_long == 0 and position.pos_short == 0 and short_ma[-3] > ema_7[-3] and short_ma[-2] < ema_7[-2]:
                        self.api.insert_order(symbol, direction="SELL", offset="OPEN", 
                                        volume=self.lots)
                        
        finally:
            self.active_symbols.remove(symbol)

    def _calculate_ma(self, q):
        """自定义权重计算（与原版完全一致）"""
        weights = np.arange(26, 0, -1)
        ma = []
        q_array = np.array(q)
        for i in range(len(q_array)):
            if i < 26:
                ma.append(np.nan)
                continue
            window = q_array[i-26:i+1]
            ma.append(np.dot(window, weights) / 351)
        
        ema_7 = EMA(pd.Series(ma), 7)
        return {'ma': ma, 'ema': ema_7.tolist()}

    async def stop(self):
        """停止策略"""
        self.running = False
        if self.main_task:
            await self.main_task
            self.main_task = None